/*
 * Copyright 2008-2023 dexian.vip. All rights reserved.
 * Support: http://www.dexian.vip
 * License: http://www.dexian.vip/license
 */

package vip.dexian.admin.security.config.custom;

import vip.dexian.admin.security.exception.CaptchaInvalidException;
import vip.dexian.admin.service.CaptchaService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;


/**
 * 自定义认证实现
 *
 * @author 挺好的 2023年06月06日 14:38
 */
public class CustomDaoAuthenticationProvider extends DaoAuthenticationProvider {

    /**
     * 增加验证码校验
     *
     * @param userDetails
     *         {@link org.springframework.security.core.userdetails.UserDetails}
     * @param authentication
     *         {@link org.springframework.security.authentication.UsernamePasswordAuthenticationToken}
     *
     * @throws org.springframework.security.core.AuthenticationException
     *         认证失败信息
     */
    @Override
    protected void additionalAuthenticationChecks (UserDetails userDetails,
            UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {

        // 如果是调试模式
        if (BooleanUtils.isTrue(this.isDebug)) {
            super.additionalAuthenticationChecks(userDetails, authentication);
            return;
        }

        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

        boolean isValid = this.isValid(request);

        if (!isValid) {
            throw new CaptchaInvalidException("captcha is not valid");
        }

        super.additionalAuthenticationChecks(userDetails, authentication);
    }

    /**
     * 验证码是否有效
     *
     * @param request
     *         {@link HttpServletRequest}
     *
     * @return 验证码是否有效
     */
    private boolean isValid (HttpServletRequest request) {
        String captcha = request.getParameter("captcha");
        if (StringUtils.isEmpty(captcha)) {
            return false;
        }

        HttpSession session = request.getSession();

        String sessionCaptcha = (String) session.getAttribute(CaptchaService.CAPTCHA_ATTRIBUTE_NAME);

        session.removeAttribute(CaptchaService.CAPTCHA_ATTRIBUTE_NAME);

        return StringUtils.equals(captcha, sessionCaptcha);
    }

    /**
     * 是否是调试模式
     */
    private Boolean isDebug;


    public Boolean getIsDebug () {
        return this.isDebug;
    }

    public void setIsDebug (Boolean isDebug) {
        this.isDebug = isDebug;
    }

}
